"""
============================
mathmodeling_SAK.Plot.reform
============================

用于在绘图过程中重塑一些变量。
"""

# 数据分析三巨头
import numpy as np
# import pandas as pd
import matplotlib.pyplot as plt

from scipy.interpolate import griddata

# from mpl_toolkits import mplot3d
# from mpl_toolkits.mplot3d import Axes3D

def df_grid_xyz(df, x='', y='', z=''):
    """
    将 pandas.DataFrame 格式化为需要绘制的三维图。
    
    对于三维绘图过程，需要首先将数据点转换为 `numpy.mershgrid` 对象，
    方可进行绘图。为了避免这样的麻烦，将这一过程封装为函数实现。
    
    示例
    ----------
    
    对于一组 `pandas.DataFrame` 类型的数据：
    
    >>> df = pd.read_csv(
        './data/附件1_重力异常基准数据A.csv')
    >>> df
           lons      lats      values
    0      115.0083  11.0068   59.3
    1      115.0250  11.0068   58.1
    2      115.0417  11.0068   52.5
    3      115.0583  11.0068   45.5
    4      115.0750  11.0068   38.4
           ...      ...    ...
    14878  116.9417   9.0045  -39.1
    14879  116.9583   9.0045  -36.0
    14880  116.9750   9.0045  -30.9
    14881  116.9917   9.0045  -24.5
    14882  117.0083   9.0045  -17.6
    
    可以通过如下的方式获得网格数据：
    
    >>> (X, Y, Z) = df_grid_xyz(
        df, x='lons', y='lats', z='values')
    
    从而进一步利用组织好的网格数据绘制需要的三维图形：
    
    >>> fig = plt.figure(dpi=300)
    >>> ax = fig.add_subplot(111, projection='3d')
    >>> ax.plot_surface(x, y, z)

    输入参数
    ----------
    df : pandas.DataFrame
        需要绘制三维视图的数据框，至少应当包含三列数据。
    x : str, optional
        需要绘制的三维数据分布情况的 x 轴数据，默认为空字符串
    y : str, optional
        需要绘制的三维数据分布情况的 y 轴数据，默认为空字符串
    z : str, optional
        需要绘制的三维数据分布情况的 z 轴数据，默认为空字符串

    返回值
    ----------
    X_grid : numpy.ndarray
        经过转换后的三维数据分布情况的 x 轴数据
    Y_grid : numpy.ndarray
        经过转换后的三维数据分布情况的 y 轴数据
    Z_grid : numpy.ndarray
        经过转换后的三维数据分布情况的 z 轴数据
    """
    # 提取 X, Y, Z 列的值
    X = df[x].values
    Y = df[y].values
    Z = df[z].values

    # 创建网格数据
    xi = np.linspace(X.min(), X.max(), 1000)
    yi = np.linspace(Y.min(), Y.max(), 1000)
    X_grid, Y_grid = np.meshgrid(xi, yi)
    Z_grid = griddata(
        (X, Y), Z, (X_grid, Y_grid), 
        method='cubic')
    
    return X_grid, Y_grid, Z_grid